package com.px.baolaiapi.filters;


import com.fasterxml.jackson.databind.ObjectMapper;

import com.px.common.api.CommonResult;
import com.px.common.domain.UserLoginParam;
import com.px.baolaiapi.dto.SecurityUser;
import com.px.baolaiapi.property.JwtProperty;
import com.px.baolaiapi.util.JwtTokenUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * @author 品讯科技
 * @date 2024-08
 * 登录认证器
 */
@Component
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    @Autowired
    private JwtProperty jwtProperty;

    @Autowired
    private JwtTokenUtils jwtTokenUtils;


    @Autowired
    @Override
    public void setAuthenticationManager(AuthenticationManager authenticationManager) {
        super.setAuthenticationManager(authenticationManager);
        super.setFilterProcessesUrl("/login/login");
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {

        try {

            // 从输入流中获取到登录的信息
            UserLoginParam loginUser = new ObjectMapper().readValue(request.getInputStream(), UserLoginParam.class);
            //交给springsecurity去做认证
            Authentication authenticate = super.getAuthenticationManager().authenticate(new UsernamePasswordAuthenticationToken(loginUser.getUsername(), loginUser.getPassword()));
            return authenticate;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 登录成功后执行的方法
     *
     * @param request
     * @param response
     * @param chain
     * @param authResult
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {

        SecurityUser principal = (SecurityUser) authResult.getPrincipal();
        String token = jwtTokenUtils.createToken(principal.getUsername(), (List<GrantedAuthority>) principal.getAuthorities());
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        response.setHeader(jwtProperty.getTOKEN_HEADER(), jwtProperty.getTOKEN_PREFIX() + " " + token);
        response.getWriter().print(new ObjectMapper().writeValueAsString(CommonResult.success(jwtProperty.getTOKEN_PREFIX() + " " + token)));
    }

    /**
     * 认证失败返回的信息
     *
     * @param request
     * @param response
     * @param failed
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        failed.printStackTrace();
        response.getWriter().print(new ObjectMapper().writeValueAsString(CommonResult.failed("用户名或密码错误")));
    }
}
